/**
 * @file
 */

#ifndef VECTOR_APPENDER_H
#define VECTOR_APPENDER_H

#include <iostream>
#include <set>
#include <vector>

/**
 * 
 */
template<class T>
class VectorAppender
{
public:
  void add_set(std::set<std::vector<T> > given);
  void generate_appends(std::vector< T > done, std::set<std::set<std::vector< T > > > remaning);
  void generate_appends();
  void get_appends(std::set<std::vector< T > > *result_location);
private:
  std::set<std::set<std::vector< T > > > store;
  std::set<std::vector< T > > result;
};

/**
 * 
 */
template<class T>
void VectorAppender<T>::generate_appends()
{
  std::vector< T > empty_done;
  generate_appends(empty_done, store);
}

/**
 * 
 */
template<class T>
void VectorAppender<T>::generate_appends(std::vector< T > done, std::set<std::set<std::vector< T > > > remaining)
{
  if (remaining.empty())
    result.insert(done);
  else
    {
      std::set<std::set<std::vector< T > > > new_remaining = remaining;
      std::set<std::vector< T > > curr_set(*(remaining.begin()));
      new_remaining.erase(curr_set);
      for(typename std::set<std::vector< T > >::iterator i = curr_set.begin();
          i != curr_set.end();
          i++)
        {
          std::vector< T > curr_done = done;
          for(typename std::vector<T>::const_iterator j = i->begin();
              j != i->end();
              j++)
              curr_done.push_back(*j);
          generate_appends(curr_done, new_remaining);
        }          
    }
}

/**
 * 
 */
template<class T>
void  VectorAppender<T>::add_set(std::set< std::vector<T> > given)
{
  store.insert(given);
}

/**
 * 
 */
template<class T>
void VectorAppender<T>::get_appends(std::set<std::vector< T > > *result_location)
{
  *result_location = result;
}

#endif // VECTOR_APPENDER_H
